package com.sunxd.zstudy.mybatise.domain.service.engine.dispatcher.interactive;

import com.sunxd.zstudy.mybatise.application.facade.request.interactive.base.BaseInteractiveJoinRequest;
import com.sunxd.zstudy.mybatise.application.facade.response.interactive.base.BaseInteractiveJoinDetailInfo;
import com.sunxd.zstudy.mybatise.domain.annotation.Capability;
import com.sunxd.zstudy.mybatise.domain.contans.consts.InteractiveErrorCode;
import com.sunxd.zstudy.mybatise.domain.contans.enums.InteractiveType;
import com.sunxd.zstudy.mybatise.domain.exception.InternalServerException;
import com.sunxd.zstudy.mybatise.domain.service.engine.handler.join.InteractiveJoinHandler;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Description:
 */
@Component
@Slf4j
public class InteractiveJoinHandlerDispatcher {

    private Map<String, InteractiveJoinHandler<? extends BaseInteractiveJoinRequest, ?>> handlerMap;

    public InteractiveJoinHandlerDispatcher(List<InteractiveJoinHandler<?,
            ?>> capabilityJoinHandlers) {
        this.handlerMap = capabilityJoinHandlers.stream()
                .collect(Collectors.toMap(handler -> {
                    Capability annotation = handler.getClass()
                            .getAnnotation(Capability.class);
                    return annotation.value();
                }, Function.identity()));
    }

    /**
     * 转发请求到对应的处理器
     *
     * @param request 参与活动请求
     * @return 参与活动响应
     */
    public BaseInteractiveJoinDetailInfo<?> dispatch(@NonNull BaseInteractiveJoinRequest request) {
        InteractiveType capabilityType = request.getInteractiveType();
        assert capabilityType != null;
        InteractiveJoinHandler<? extends BaseInteractiveJoinRequest, ?> handler =
                handlerMap.get(
                        request.getInteractiveType().name());
        if (handler == null) {
            log.error("capabilityKey: {} did not match any handler", request.getInteractiveType());
            throw new InternalServerException(InteractiveErrorCode.INTERNAL_SERVER_ERROR);
        }
        try{
            return  (BaseInteractiveJoinDetailInfo<?>) handler.getClass().getMethod("join",
                    ((ParameterizedType)handler.getClass().getGenericSuperclass()).getActualTypeArguments()[0].getClass())
                    .invoke(handler, request);

        }catch (InvocationTargetException e) {
            log.error("error when join campaign,campaignId:{}",request.getActivityCode(),
                    e);
            if(e.getTargetException() instanceof InternalServerException) {
                throw new InternalServerException(((InternalServerException) e.getTargetException()).getCode());
            }
            throw new InternalServerException(InteractiveErrorCode.INTERNAL_SERVER_ERROR);
        }catch (Exception e) {
            log.error("error when join campaign,campaignId:{}",request.getActivityCode());
            throw new InternalServerException(InteractiveErrorCode.INTERNAL_SERVER_ERROR);
        }
    }

}
